package com.living.player.widget.media;

import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.SeekBar;
import android.widget.TextView;

import com.living.R;

import java.util.Formatter;
import java.util.Locale;

/**
 * 动态化 底部Bar
 * <p>
 * 缓存里面的音视频右小角没有退出全屏按钮 ，视频显示倍率（有就显示）、本地；音频显示倍率（有就显示）、本地；退出全屏按钮没有之后，倍率和本地整体又移
 * <p>
 *
 * @author wanggq
 * @description:
 * @date :2019-12-27 10:14
 */
public class CustomMediaController extends FrameLayout implements IMediaController {

    final String TAG = "SimpleMediaController";

    private MediaController.MediaPlayerControl mPlayer;
    private Context mContext;
    private View mRoot;
    private SeekBar mProgress;
    private TextView mEndTime;
    private TextView mCurrentTime;
    private boolean mShowing = true;
    private boolean mDragging;
    private static final int sDefaultTimeout = 3000;
    private boolean mListenersSet;
    private View.OnClickListener mNextListener, mPrevListener;
    StringBuilder mFormatBuilder;
    Formatter mFormatter;
    private ImageView mPauseButton;
    private ImageView mNextButton;
    private ImageView mPrevButton;
    private ImageView mOrderButton;
    private ImageView mMenuButton;
    private CharSequence mPlayDescription;
    private CharSequence mPauseDescription;

    public ImageView getmOrderButton() {
        return mOrderButton;
    }

    public ImageView getmMenuButton() {
        return mMenuButton;
    }

    public CustomMediaController(Context context) {
        super(context);
        mContext = context;
        initView();
    }

    public CustomMediaController(Context context, AttributeSet attrs) {
        super(context, attrs);
        mRoot = this;
        mContext = context;
        initView();
    }

    private void initView() {
        FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        removeAllViews();
        View v = makeControllerView();
        addView(v, frameParams);
    }

//    @Override
//    public void onFinishInflate() {
//        super.onFinishInflate();
//        if (mRoot != null)
//            initControllerView(mRoot);
//    }

    @Override
    public void setMediaPlayer(MediaController.MediaPlayerControl player) {
        mPlayer = player;
        updatePausePlay();
    }

    /**
     * Set the view that acts as the anchor for the control view.
     * This can for example be a VideoView, or your Activity's main view.
     * When VideoView calls this method, it will use the VideoView's parent
     * as the anchor.
     *
     * @param view The view to which to anchor the controller when it is visible.
     */
    @Override
    public void setAnchorView(View view) {
//        mAnchor = view;
//        FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//        removeAllViews();
//        View v = makeControllerView();
//        addView(v, frameParams);
    }

    /**
     * Create the view that holds the widgets that control playback.
     * Derived classes can override this to create their own.
     *
     * @return The controller view.
     * @hide This doesn't work as advertised
     */
    protected View makeControllerView() {
        LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mRoot = inflate.inflate(R.layout.ph_player_audio_controller_layout, null);
        initControllerView(mRoot);
        return mRoot;
    }

    private void initControllerView(View v) {
        mPlayDescription = "播放";
        mPauseDescription = "暂停";
        mPauseButton = v.findViewById(R.id.im_sdk_player_status);
        if (mPauseButton != null) {
            mPauseButton.requestFocus();
            mPauseButton.setOnClickListener(mPauseListener);
        }
        // By default these are hidden. They will be enabled when setPrevNextListeners() is called
        mNextButton = v.findViewById(R.id.im_sdk_player_next);
        if (mNextButton != null && !mListenersSet) {
            mNextButton.setVisibility(View.VISIBLE);
        }
        mPrevButton = v.findViewById(R.id.im_sdk_player_last);
        if (mPrevButton != null && !mListenersSet) {
            mPrevButton.setVisibility(View.VISIBLE);
        }
        mOrderButton = v.findViewById(R.id.im_sdk_player_order_switch);
        mMenuButton = v.findViewById(R.id.im_sdk_player_menu);

        mProgress = v.findViewById(R.id.sb_sdk_player_seekbar);
        if (mProgress != null) {
            if (mProgress instanceof SeekBar) {
                SeekBar seeker = (SeekBar) mProgress;
                seeker.setOnSeekBarChangeListener(mSeekListener);
            }
            mProgress.setMax(1000);
        }
        mEndTime = v.findViewById(R.id.tv_sdk_player_duration);
        mCurrentTime = v.findViewById(R.id.tv_sdk_player_current_time);
        mFormatBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());

        installPrevNextListeners();
    }


    @Override
    public void showOnce(View view) {
        view.setVisibility(View.VISIBLE);
        show();
    }

    /**
     * Disable pause or seek buttons if the stream cannot be paused or seeked. This requires the control interface to be a MediaPlayerControlExt
     */
    private void disableUnsupportedButtons() {
        if (mPlayer == null) {
            return;
        }
        try {
            if (mPauseButton != null && !mPlayer.canPause()) {
                mPauseButton.setEnabled(false);
            }
            // shouldn't arise in existing applications.
            if (mProgress != null && !mPlayer.canSeekBackward() && !mPlayer.canSeekForward()) {
                mProgress.setEnabled(false);
            }
        } catch (IncompatibleClassChangeError ex) {
            // We were given an old version of the interface, that doesn't have
        }
    }

    /**
     * Show the controller on screen. It will go away automatically after 3 seconds of inactivity.
     */
    @Override
    public void show() {
        show(sDefaultTimeout);
    }

    /**
     * Show the controller on screen. It will go away
     * automatically after 'timeout' milliseconds of inactivity.
     *
     * @param timeout The timeout in milliseconds. Use 0 to show
     *                the controller until hide() is called.
     */
    @Override
    public void show(int timeout) {
//        if (!mShowing) {
        setProgress();
        if (mPauseButton != null) {
            mPauseButton.requestFocus();
        }
        disableUnsupportedButtons();
        mShowing = true;
//        }
        updatePausePlay();
        // paused with the progress bar showing the user hits play.
        post(mShowProgress);
        if (timeout != 0) {
            removeCallbacks(mFadeOut);
            postDelayed(mFadeOut, timeout);
        }
    }

    @Override
    public boolean isShowing() {
        return mShowing;
    }

    /**
     * Remove the controller from the screen.
     */
    @Override
    public void hide() {
//        if (mAnchor == null)
//            return;
//        if (mShowing) {
        try {
            removeCallbacks(mShowProgress);
        } catch (IllegalArgumentException ex) {
            Log.w("MediaController", "already removed");
        }
//            mShowing = true;
//        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        try {
            removeCallbacks(mShowProgress);
        } catch (IllegalArgumentException ex) {
            Log.w("MediaController", "already removed");
        }
    }

    private final Runnable mFadeOut = new Runnable() {
        @Override
        public void run() {
//            hide();
        }
    };

    private final Runnable mShowProgress = new Runnable() {
        @Override
        public void run() {
            if (mPlayer == null) {
                return;
            }
            int pos = setProgress();
            if (!mDragging && mShowing && mPlayer.isPlaying()) {
                postDelayed(mShowProgress, 1000 - (pos % 1000));
            }
        }
    };

    private String stringForTime(int timeMs) {
        int totalSeconds = timeMs / 1000;
        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours = totalSeconds / 3600;
        mFormatBuilder.setLength(0);
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    private int setProgress() {
        if (mPlayer == null || mDragging) {
            return 0;
        }
        int position = mPlayer.getCurrentPosition();
        int duration = mPlayer.getDuration();
        if (mProgress != null) {
            if (duration > 0) {
                // use long to avoid overflow
                long pos = 1000L * position / duration;
                mProgress.setProgress((int) pos);
            }
            int percent = mPlayer.getBufferPercentage();
            mProgress.setSecondaryProgress(percent * 10);
        }

        if (mEndTime != null)
            mEndTime.setText(stringForTime(duration));
        if (mCurrentTime != null)
            mCurrentTime.setText(stringForTime(position));

        return position;
    }

    private final View.OnClickListener mPauseListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (onPauseResumeListener != null && onPauseResumeListener.isCanPauseResume()) {
                doPauseResume();
                show(sDefaultTimeout);
            }
        }
    };


    OnPauseResumeListener onPauseResumeListener;

    public void setOnPauseListeners(OnPauseResumeListener onPauseListeners) {
        this.onPauseResumeListener = onPauseListeners;
    }

    public void updatePausePlay() {
        if (mRoot == null || mPauseButton == null || mPlayer == null)
            return;
        if (mPlayer.isPlaying()) {
            mPauseButton.setImageResource(R.drawable.icon_player_media_pause);
            mPauseButton.setContentDescription(mPauseDescription);
        } else {
            mPauseButton.setImageResource(R.drawable.icon_player_media_play);
            mPauseButton.setContentDescription(mPlayDescription);
        }
    }

    private void doPauseResume() {
        if (mPlayer == null) return;
        if (mPlayer.isPlaying()) {
            mPlayer.pause();
        } else {
            mPlayer.start();
        }
        updatePausePlay();
    }

    private final SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onStartTrackingTouch(SeekBar bar) {
            show(3600000);
            mDragging = true;
            // this ensures that there will be exactly one message queued up.
            removeCallbacks(mShowProgress);
        }

        @Override
        public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
            if (!fromuser) {
                // We're not interested in programmatically generated changes to
                return;
            }
            long duration = mPlayer.getDuration();
            long newposition = (duration * progress) / 1000L;
            mPlayer.seekTo((int) newposition);
            if (mCurrentTime != null)
                mCurrentTime.setText(stringForTime((int) newposition));
        }

        @Override
        public void onStopTrackingTouch(SeekBar bar) {
            mDragging = false;
            setProgress();
            updatePausePlay();
            show(sDefaultTimeout);
            // no-op if we are already showing.
            post(mShowProgress);
        }
    };

    @Override
    public void setEnabled(boolean enabled) {
        if (mPauseButton != null) {
            mPauseButton.setEnabled(enabled);
        }
        if (mNextButton != null) {
            mNextButton.setEnabled(enabled && mNextListener != null);
        }
        if (mPrevButton != null) {
            mPrevButton.setEnabled(enabled && mPrevListener != null);
        }
        if (mProgress != null) {
            mProgress.setEnabled(enabled);
        }
        disableUnsupportedButtons();
        super.setEnabled(enabled);
    }

    @Override
    public CharSequence getAccessibilityClassName() {
        return MediaController.class.getName();
    }

    private void installPrevNextListeners() {
        if (mNextButton != null) {
            mNextButton.setOnClickListener(mNextListener);
            mNextButton.setEnabled(mNextListener != null);
        }
        if (mPrevButton != null) {
            mPrevButton.setOnClickListener(mPrevListener);
            mPrevButton.setEnabled(mPrevListener != null);
        }
    }

    public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
        mNextListener = next;
        mPrevListener = prev;
        mListenersSet = true;
        if (mRoot != null) {
            installPrevNextListeners();
            if (mNextButton != null) {
                mNextButton.setVisibility(View.VISIBLE);
            }
            if (mPrevButton != null) {
                mPrevButton.setVisibility(View.VISIBLE);
            }
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                show(0); // show until hide is called
                break;
            case MotionEvent.ACTION_UP:
                show(sDefaultTimeout); // start timeout
                break;
            case MotionEvent.ACTION_CANCEL:
//                hide();
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    public boolean onTrackballEvent(MotionEvent ev) {
        show(sDefaultTimeout);
        return false;
    }


}
